from django.db import models
from django.forms.models import model_to_dict
from apps.resource.models import Business, Project, Service, Environment, DockerRepo, Kubernetes
from .enums import OrderChoices, RunningStatusChoices, ResultStatusChoices, UpdateChoices
# Create your models here.



class Flow(models.Model):
    name = models.CharField(max_length=25, verbose_name='名称')
    function = models.CharField(max_length=64, verbose_name='方法')
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', null=True)
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间', null=True)
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    # def get_steps(self, last_step=None, **kwargs):
    #     steps = []
    #     if last_step == None:
    #         last_step = self.steps.get(function='init')
    #     while 1:
    #         next_step = last_step.yes_step
    #         if not next_step: break
    #         next_step_function = next_step.function
    #         next_step_function_key = next_step_function.split('__')[-1]
    #         next_step_function_key = re.sub('_auto', '', next_step_function_key)
    #         if kwargs.get(next_step_function_key)==None or kwargs.get(next_step_function_key)==1:
    #             steps.append({
    #                 'step_name': next_step.name,
    #                 'step': next_step.function,
    #                 # 'opuser': next_step.opuser,
    #                 'status': 'wait'
    #             })
    #         last_step = next_step
    #         if last_step.function == 'cancel': break
    #     return steps


    # def get_stages(self):
    #     stages = []
    #     for stage in self.stages.order_by('order'):
    #         stages.append({
    #             'name': stage.name,
    #             'function': stage.function
    #         })
    #     return stages
    #
    # def get_steps(self, last_stage=None, last_step=None, last_step_env=None,next_loop_envs=[]):
    #     steps = []
    #     for stage in self.stages.order_by('order'):
    #         if last_stage and stage.order < last_stage.order:continue
    #         # if stage.order < last_stage.order:continue
    #         if not (last_step_env == None and stage.env_loop):
    #             nextsteps = stage.get_steps(last_step=last_step, env=last_step_env)
    #             steps += nextsteps
    #             last_step = None
    #
    #         if stage.env_loop and len(next_loop_envs)>=0:
    #             if len(steps)>0 and steps[-1].get('step') == 'cancel': break
    #             for next_loop_env in next_loop_envs:
    #                 nextsteps = stage.get_steps(env=next_loop_env)
    #                 steps += nextsteps
    #                 last_step = None
    #             last_step_env = None
    #
    #
    #     return steps

    # def next_stage(self, last_stage):
    #     next_stage = self.stages.filter(order__gt=last_stage.order).first()
    #     return next_stage
# class Stage(models.Model):
#     name = models.CharField(max_length=25, verbose_name='名称')
#     function = models.CharField(max_length=64, verbose_name='方法')
#     env_loop = models.BooleanField(verbose_name='环境循环', default=False)
#     created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', null=True)
#     updated = models.DateTimeField(auto_now=True, verbose_name='更新时间', null=True)
#     comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)
#
#
#     def steps(self, env=None):
#         stagestep = self.steps.get(function=self.function+'_init')
#         steps = []
#         while 1:
#             next_step = stagestep.yes_step
#
#
# class Step(models.Model):
#     name = models.CharField(max_length=25, verbose_name='名称')
#     function = models.CharField(max_length=64, verbose_name='方法')
#     perm_role = models.CharField(max_length=25, verbose_name='授权角色', null=True)
#     created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', null=True)
#     updated = models.DateTimeField(auto_now=True, verbose_name='更新时间', null=True)
#     comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

# class Stage(models.Model):
#     flow = models.ForeignKey(Flow, verbose_name='流程', on_delete=models.CASCADE, related_name='stages')
#     order = models.IntegerField(verbose_name='次序')
#     # stage = models.ForeignKey(Stage, verbose_name='阶段', on_delete=models.CASCADE)
#     # stage = models.CharField(max_length=25, verbose_name='阶段')
#     name = models.CharField(max_length=25, verbose_name='名称')
#     function = models.CharField(max_length=64, verbose_name='方法')
#     env_loop = models.BooleanField(verbose_name='环境循环', default=False)
#
#     created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
#     updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
#     comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)
#
#     def get_steps(self, last_step=None, env=None):
#         steps = []
#         if last_step == None:
#             last_step = self.steps.get(function='init')
#         while 1:
#             next_step = last_step.yes_step
#             if not next_step: break
#             steps.append({
#                 'step_name': next_step.name if env == None else next_step.name+'-'+env,
#                 'step': next_step.function,
#                 # 'opuser': next_step.opuser,
#                 'status': 'wait'
#             })
#             last_step = next_step
#             if last_step.function == 'cancel': break
#         return steps




class Step(models.Model):
    # stage = models.ForeignKey(Stage, verbose_name='阶段', on_delete=models.CASCADE, related_name='steps')
    flow = models.ForeignKey(Flow, verbose_name='流程', on_delete=models.CASCADE, related_name='steps')
    # step = models.ForeignKey(Step, verbose_name='步骤', on_delete=models.CASCADE, related_name='stagestep')
    name = models.CharField(max_length=25, verbose_name='名称')
    function = models.CharField(max_length=64, verbose_name='方法')
    perm_role = models.CharField(max_length=25, verbose_name='授权角色', null=True)
    yes_button = models.CharField(max_length=255, verbose_name='YES按钮', null=True)
    yes_step = models.ForeignKey('self', verbose_name='YES步骤', on_delete=models.CASCADE, null=True, related_name='yes')
    no_button = models.CharField(max_length=255, verbose_name='NO按钮', null=True)
    no_step = models.ForeignKey('self', verbose_name='NO步骤', on_delete=models.CASCADE, null=True, related_name='no')
    hidden_button = models.IntegerField(default=0, verbose_name='隐藏button')
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)



class Capacity(models.Model):
    name = models.CharField(max_length=25, verbose_name='名称')
    cpu = models.DecimalField(decimal_places=2, max_digits=3, verbose_name='核心数')
    # memory = models.IntegerField(verbose_name='内存(G)')
    memory = models.DecimalField(decimal_places=1, max_digits=2, verbose_name='内存(G)')
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    def __str__(self):
        return self.name

class YAMLTemplate(models.Model):
    name = models.CharField(max_length=25, verbose_name='名称')
    yaml = models.TextField(verbose_name='YAML')
    # params = models.TextField(verbose_name='额外环境参数')

    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    def __str__(self):
        return self.name


class LobEnvSetting(models.Model):
    namespace = models.CharField(max_length=25, verbose_name='命名空间', null=True, blank=True, default=None)
    replicas = models.IntegerField(default=1, verbose_name='副本数')
    repo_namespace_src = models.CharField(max_length=64, verbose_name='仓库命名空间同步源', null=True, blank=True)
    repo_namespace = models.CharField(max_length=64, verbose_name='仓库命名空间', null=True, blank=True)
    repo_pull_secret = models.CharField(max_length=64, verbose_name='仓库镜像秘钥', null=True, default=None)
    git_merge = models.IntegerField(verbose_name='Git合并', default=0, null=True)
    auto_audit = models.IntegerField(verbose_name='自动审核', default=0)
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    business_id = models.IntegerField(verbose_name='业务线编号')
    project_id = models.IntegerField(verbose_name='项目编号', null=True, default=None)
    service_id = models.IntegerField(verbose_name='服务编号', null=True, default=None)
    env_id = models.IntegerField(verbose_name='环境编号')
    kube_id = models.IntegerField(verbose_name='集群编号', null=True, default=None)
    capacity_id = models.IntegerField(verbose_name='计算方案编号', null=True, default=None)
    template_id = models.IntegerField(verbose_name='yaml模板编号', null=True, default=None)
    repo_id = models.IntegerField(verbose_name='repo编号', null=True, default=None)
    nodeploy = models.IntegerField(verbose_name='拒绝部署', default=0)
    # class Meta:
    #     unique_together = (('business', 'project', 'service', 'env'))
    #
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['business_id', 'project_id', 'service_id', 'env_id'], name='配置唯一')
        ]
    @property
    def business(self):
        return Business.objects.filter(id=self.business_id).first() if self.business_id else None
    @property
    def project(self):
        return Project.objects.filter(id=self.project_id).first() if self.project_id else None
    @property
    def service(self):
        return Service.objects.filter(id=self.service_id).first() if self.service_id else None
    @property
    def env(self):
        return Environment.objects.filter(id=self.env_id).first() if self.env_id else None
    @property
    def kube(self):
        return Kubernetes.objects.filter(id=self.kube_id).first() if self.kube_id else None
    @property
    def capacity(self):
        return Capacity.objects.filter(id=self.capacity_id).first() if self.capacity_id else None
    @property
    def template(self):
        return YAMLTemplate.objects.filter(id=self.template_id).first() if self.template_id else None
    @property
    def repo(self):
        return DockerRepo.objects.filter(id=self.repo_id).first() if self.repo_id else None



class LobYamlSetting(models.Model):
    business_id = models.IntegerField(verbose_name='业务线编号')
    project_id = models.IntegerField(verbose_name='项目编号', null=True)
    service_id = models.IntegerField(verbose_name='服务编号', null=True)
    env_id = models.IntegerField(verbose_name='环境编号')
    template = models.ForeignKey(YAMLTemplate, verbose_name='yaml模板', on_delete=models.CASCADE)
    params = models.TextField(verbose_name='额外环境参数', null=True, blank=True)

    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)


class DemandOrder(models.Model):
    name = models.CharField(max_length=255, verbose_name='迭代', default=None)
    business_id = models.IntegerField(verbose_name='业务线ID')
    env_id = models.IntegerField(verbose_name='环境ID')
    step_id = models.IntegerField(verbose_name='步骤ID', null=True, default=None)

    # business = models.ForeignKey(Business, verbose_name='业务线', on_delete=models.CASCADE)
    order_type = models.CharField(choices=OrderChoices, max_length=25, verbose_name='工单类型')
    update_type = models.CharField(choices=UpdateChoices, max_length=25, verbose_name='更新类型', null=True)
    # env = models.ForeignKey(Environment, verbose_name='环境', on_delete=models.CASCADE)
    expected_time = models.DateTimeField(verbose_name='期望时间', null=True, default=None)
    # step = models.ForeignKey(Step, verbose_name='步骤', on_delete=models.CASCADE, null=True, default=None)
    status = models.CharField(max_length=25, choices=RunningStatusChoices, verbose_name='运行状态', default='wait')
    result = models.CharField(max_length=25, choices=ResultStatusChoices, verbose_name='结果', null=True, default=None)
    creator = models.CharField(max_length=25, verbose_name='申请者', null=True)
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.TextField(verbose_name='备注', null=True, blank=True)

    @property
    def business(self):
        return Business.objects.filter(id=self.business_id).first() if self.business_id else None

    @property
    def env(self):
        return Environment.objects.filter(id=self.env_id).first() if self.env_id else None

    @property
    def step(self):
        return Step.objects.filter(id=self.step_id).first() if self.step_id else None


    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['name', 'business_id', 'env_id'], name='迭代唯一')
        ]

class WorkOrder(models.Model):
    demand = models.ForeignKey(DemandOrder, verbose_name='母单', related_name='orders', default=None, null=True, on_delete=models.CASCADE)
    service_id = models.IntegerField(verbose_name='服务ID')
    env_id = models.IntegerField(verbose_name='环境ID')

    # service = models.ForeignKey(Service, verbose_name='服务', on_delete=models.CASCADE)
    order_type = models.CharField(choices=OrderChoices, max_length=25, verbose_name='工单类型')
    update_type = models.CharField(choices=UpdateChoices, max_length=25, verbose_name='更新类型', null=True)
    # env = models.ForeignKey(Environment, verbose_name='环境', null=True, on_delete=models.CASCADE)
    expected_time = models.DateTimeField(verbose_name='期望时间', null=True, default=None)
    replicas = models.IntegerField(null=True, default=None, verbose_name='副本数')
    cur_image = models.CharField(max_length=255, verbose_name='当前镜像', null=True, default=None)
    version = models.CharField(max_length=64, verbose_name='版本号', null=True, default=None)
    capacity_id = models.IntegerField(verbose_name='计算方案编号', null=True, default=None)
    yaml = models.TextField(verbose_name='Yaml', null=True, default=None)
    status = models.CharField(max_length=25, choices=RunningStatusChoices, verbose_name='运行状态', default='wait')
    result = models.CharField(max_length=25, choices=ResultStatusChoices, verbose_name='结果', null=True, default=None)
    delete = models.BooleanField(default=False, verbose_name='是否删除')
    creator = models.CharField(max_length=25, verbose_name='申请者', null=True)
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    @property
    def service(self):
        return Service.objects.filter(id=self.service_id).first() if self.service_id else None
    @property
    def env(self):
        return Environment.objects.filter(id=self.env_id).first() if self.env_id else None
    @property
    def capacity(self):
        return Capacity.objects.filter(id=self.capacity_id).first() if self.capacity_id else None

    @property
    def setting(self):
        lobsetting = LobEnvSetting.objects.filter(business_id=self.service.business.id, project_id__isnull=True).first()
        return lobsetting

    @property
    def nodeploy(self):
        lobsetting = LobEnvSetting.objects.filter(service_id=self.service_id, env_id=self.env_id).first()
        if not lobsetting:
            return 0
        return lobsetting.nodeploy

    @property
    def order_type_name(self):
        return dict(OrderChoices).get(self.order_type)

    def get_flow_obj(self):
        if self.order_type == 'update':
            flow = Flow.objects.get(function='UpdateFlow')
            return flow
        elif self.order_type == 'restart':
            flow = Flow.objects.get(function='RestartFlow')
            return flow
        elif self.order_type == 'scale':
            flow = Flow.objects.get(function='ScaleFlow')
            return flow
        elif self.order_type == 'regrade':
            flow = Flow.objects.get(function='RegradeFlow')
            return flow
    # 
    # def get_next_step_function(self, action=None):
    #     current_step = self.steps.last().get_step_obj()
    #     next_step = current_step.no_step
    #     next_step_env = None
    #     if action == 'yes':
    #         if not next_step:
    #             current_stage = current_step.stage
    #             if current_stage.env_loop and envs.index(current_step_env) != len(envs) - 1:
    #                 next_step_env = envs[envs.index(current_step_env)]
    #                 next_step = current_stage.steps.get(function='init').yes_step
    #             else:
    #                 flow = self.get_flow_obj()
    #                 next_stage = flow.next_stage(current_stage)
    #                 if next_stage.env_loop:
    #                     next_step_env = envs[0]
    #                 next_step = next_stage.steps.get(function='init').yes_step
    #     return next_step, next_step_env
    # 
    # 
    # def get_next_step(self, step_id, action):
    #     flow = self.get_flow_obj()
    #     order_step = self.steps.last()
    #     current_step = order_step.get_step_obj()
    #     current_step_env = order_step.step_env
    #     next_step_env = current_step_env
    #     envs = self.envs.split(',')
    #     if str(current_step.id) != step_id:
    #         return {'msg': 'STEP_NOT_MATCHED', 'next_step': None}
    #     if order_step.status != 'wait' and action in ['yes', 'no']:
    #         return {'msg': 'STEP_NOT_WAIT', 'next_step': None}
    #     next_step = getattr(current_step, '%s_step'%action)
    #     if next_step == None:
    #         current_stage = current_step.stage
    # 
    #         if current_stage.env_loop and envs.index(current_step_env) != len(envs) - 1:
    #             next_step_env = envs[envs.index(current_step_env)]
    #             next_step = current_stage.steps.get(function='init').yes_step
    #         else:
    #             next_step_env = None
    #             next_stage = flow.next_stage(current_stage)
    #             if next_stage == None:
    #                 return {'msg':'STEP_IS_END', 'next_step': None}
    #             if next_stage.env_loop:
    #                 next_step_env = envs[0]
    #             next_step = next_stage.steps.get(function='init').yes_step
    #         return {'next_step_env': next_step_env, 'next_step': next_step}
    #     else:
    #         return {'next_step_env': next_step_env, 'next_step': next_step}
    # 



    # def flow_steps(self):
    #     steps = []
    #     current_stage = self.steps.last().stage
    #     current_step = self.steps.last().step
    #     current_step_env = self.steps.last().step_env
    #     for step in self.steps:
    #         steps.append({
    #             'step_name': step.step_name,
    #             'status': step.status,
    #             'opuser': step.opuser,
    #         })
    #     while 1:
    #         if current_step.yes:
    #             current_step = current_step.yes
    #             steps.append(
    #                 {
    #                     'step_name': current_step.step_name,
    #                     'status': current_step.status
    #                 }
    #             )
    #         else:
    #             break
    #     while 1:
    #         if current_stage.env_loop and self.envs[-1] != current_step_env:
    #             for env in self.envs[self.envs.index(current_step_env)+1:]:
    #                 step = current_stage.steps.first()
    #
    #
    #






class WorkOrderStep(models.Model):
    workorder = models.ForeignKey(WorkOrder, verbose_name='工单', related_name='steps', on_delete=models.CASCADE)

    # step = models.ForeignKey(Step, verbose_name='步骤', on_delete=models.CASCADE)
    step_id = models.IntegerField(verbose_name='步骤ID')

    opuser = models.CharField(max_length=25, verbose_name='操作用户', null=True)
    status = models.CharField(max_length=25, choices=RunningStatusChoices, verbose_name='状态', default='wait')
    result = models.CharField(max_length=25, verbose_name='结果', null=True)
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    comment = models.CharField(max_length=255, verbose_name='备注', null=True, blank=True)

    @property
    def step(self):
        return Step.objects.filter(id=self.step_id).first() if self.step_id else None

    # class Meta:
    #     # unique_together = ( ('workorder', 'step_function', 'step_env') )
    #     unique_together = ( ('workorder', 'step') )
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['workorder', 'step_id'], name='工单步骤唯一')
        ]
    # def get_step_obj(self):
    #     flow = self.workorder.get_flow_obj()
    #     stage_function = self.step_function.split('__')[0]
    #     step_function = self.step_function.split('__')[1]
    #     return flow.stages.get(function=stage_function).steps.get(
    #         function=step_function)